//
//  JHXMPPManager.m
//  JHChat
//
//  Created by JiaHao on 2/22/15.
//  Copyright (c) 2015 JiaHao. All rights reserved.
//

#import "JHXMPPManager.h"
#import "XMPPMessage+XEP_0085.h"
#import "XMPPvCardTemp.h"

@implementation JHXMPPManager

+ (instancetype)sharedManager
{
    static JHXMPPManager *_sharedManager = nil;
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        _sharedManager = [[self alloc ] init];
    });
    
    return _sharedManager;
}

-(XMPPJID *)myJID
{
  return [_xmppStream myJID];
}

- (NSManagedObjectContext *)managedObjectContext_roster
{
    return [_xmppRosterStorage mainThreadManagedObjectContext];
}

- (NSManagedObjectContext *)managedObjectContext_capabilities
{
    return [_xmppCapabilitiesStorage mainThreadManagedObjectContext];
}

- (NSManagedObjectContext *)managedObjectContext_messageArchiving
{
    return [_xmppMessageArchivingCoreDataStorage mainThreadManagedObjectContext];
}



- (void)dealloc
{
    [self teardownStream];
}


- (void)teardownStream
{
    [_xmppStream removeDelegate:self];
    [_xmppRoster removeDelegate:self];
    [_xmppMessageArchiving removeDelegate:self];
    
    [_xmppReconnect         deactivate];
    [_xmppRoster            deactivate];
    [_xmppvCardTempModule   deactivate];
    [_xmppvCardAvatarModule deactivate];
    [_xmppCapabilities      deactivate];
    [_xmppMessageArchiving  deactivate];
    
    [_xmppStream disconnect];
    
    _xmppStream = nil;
    _xmppReconnect = nil;
    _xmppRoster = nil;
    _xmppRosterStorage = nil;
    _xmppvCardStorage = nil;
    _xmppvCardTempModule = nil;
    _xmppvCardAvatarModule = nil;
    _xmppCapabilities = nil;
    _xmppCapabilitiesStorage = nil;
    _xmppMessageArchiving = nil;
    _xmppMessageArchivingCoreDataStorage = nil;
}


-(void)setUpXmpp
{
    
    self.xmppStream = [[XMPPStream alloc]init];

#if !TARGET_IPHONE_SIMULATOR
    {
        _xmppStream.enableBackgroundingOnSocket = YES;
    }
#endif
    
    //重连组件
    _xmppReconnect = [[XMPPReconnect alloc]init];
    
    //花名册
    _xmppRosterStorage = [[XMPPRosterCoreDataStorage alloc]init];
    _xmppRosterStorage.autoRemovePreviousDatabaseFile = NO;
    _xmppRosterStorage.autoRecreateDatabaseFile = NO;
    _xmppRoster = [[XMPPRoster alloc]initWithRosterStorage:self.xmppRosterStorage];
    [_xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
    
    //自动获取用户列表
    _xmppRoster.autoFetchRoster = YES;
    _xmppRoster.autoAcceptKnownPresenceSubscriptionRequests = NO;
    
    //message store
    self.xmppMessageArchivingCoreDataStorage = [[XMPPMessageArchivingCoreDataStorage alloc] init];
    self.xmppMessageArchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:self.xmppMessageArchivingCoreDataStorage];
    
    [_xmppMessageArchiving setClientSideMessageArchivingOnly:YES];
    [_xmppMessageArchiving addDelegate:self delegateQueue:dispatch_get_main_queue()];
    
    _xmppvCardStorage = [XMPPvCardCoreDataStorage sharedInstance];
    _xmppvCardTempModule = [[XMPPvCardTempModule alloc] initWithvCardStorage:_xmppvCardStorage];
    
    _xmppvCardAvatarModule = [[XMPPvCardAvatarModule alloc] initWithvCardTempModule:_xmppvCardTempModule];
    
    _xmppCapabilitiesStorage = [XMPPCapabilitiesCoreDataStorage sharedInstance];
    _xmppCapabilities = [[XMPPCapabilities alloc] initWithCapabilitiesStorage:_xmppCapabilitiesStorage];
    _xmppCapabilities.autoFetchHashedCapabilities = YES;
    _xmppCapabilities.autoFetchNonHashedCapabilities = NO;
    
    [self.xmppMessageArchiving activate:self.xmppStream];
    [self.xmppReconnect activate:self.xmppStream];
    [self.xmppRoster activate:self.xmppStream];
    [self.xmppvCardTempModule   activate:self.xmppStream];
    [self.xmppvCardAvatarModule activate:self.xmppStream];
    [self.xmppCapabilities      activate:self.xmppStream];
    
    [_xmppStream addDelegate:self delegateQueue:dispatch_get_main_queue()];
    [_xmppRoster addDelegate:self delegateQueue:dispatch_get_main_queue()];
    [_xmppMessageArchiving addDelegate:self delegateQueue:dispatch_get_main_queue()];
    
}


- (void)goOnline
{
    XMPPPresence *presence = [XMPPPresence presence]; // type="available" is implicit
    
    [[self xmppStream] sendElement:presence];
}

- (void)goOffline
{
    XMPPPresence *presence = [XMPPPresence presenceWithType:@"unavailable"];
    
    [[self xmppStream] sendElement:presence];
}


- (void)sendChatMessage:(NSString *)plainMessage toJID:(XMPPJID *)jid
{
    if (plainMessage.length > 0 && jid.user.length > 0) {
        NSXMLElement *body = [NSXMLElement elementWithName:@"body"];
        [body setStringValue:plainMessage];
        
        NSXMLElement *message = [NSXMLElement elementWithName:@"message"];
        [message addAttributeWithName:@"type" stringValue:@"chat"];
        [message addAttributeWithName:@"to" stringValue:jid.full];
        
        [message addChild:body];
        
        XMPPMessage * xMessage = [XMPPMessage messageFromElement:message];
        [xMessage addActiveChatState];
        
        [[JHXMPPManager sharedManager].xmppStream sendElement:message];
    }
}

// 设置nickname
- (void)updateNickName
{
    XMPPvCardTemp *myvCardTemp = [[self xmppvCardTempModule] myvCardTemp];
    if (myvCardTemp) {
        myvCardTemp.nickname = @"jhtest";
        [[self xmppvCardTempModule] updateMyvCardTemp:myvCardTemp];
    }
}


//好友状态改变  上线下线等
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
    NSLog(@"好友状态变化: %@",presence.description);

    if ([[presence type] isEqualToString:@"subscribe"]) {

     [self.xmppRoster acceptPresenceSubscriptionRequestFrom:[presence from] andAddToRoster:YES];
    }
    // 对方取消加好友请求
    else if ([[presence type] isEqualToString:@"unsubscribe"]) {
        NSLog(@"对方取消加好友");
    }

    // 对方接受加好友
    //<presence from="fff@192.168.0.84" to="yj26599@192.168.0.84" type="subscribed"></presence>

    else if ([[presence type] isEqualToString:@"subscribed"]) {
        NSLog(@"对方接受加好友");

    }

    // 对方取消好友关系
    //<presence xmlns="jabber:client" from="aaa@192.168.0.84" to="yj26599@192.168.0.84" type="unsubscribed"></presence>

    else if ([[presence type] isEqualToString:@"unsubscribed"]) {

        NSLog(@"对方删了你！");

    }
}

#pragma mark - XMPPStreamDelegate

- (void)xmppStreamWillConnect:(XMPPStream *)sender
{
    NSLog(@"xmppStreamWillConnect");
}
- (void)xmppStreamDidConnect:(XMPPStream *)sender
{
    NSLog(@"xmppStreamDidConnect");
}


- (void)xmppRoster:(XMPPRoster *)sender didReceivePresenceSubscriptionRequest:(XMPPPresence *)presence
{
    //<presence xmlns="jabber:client" id="XWyMu-52" to="aaa@192.168.0.84" type="subscribe" from="uuu@192.168.0.84"></presence>
    XMPPUserCoreDataStorageObject *user = [_xmppRosterStorage userForJID:[presence from]
                                                              xmppStream:_xmppStream
                                                    managedObjectContext:[self managedObjectContext_roster]];

    NSString *displayName = [user displayName];
    NSString *jidStrBare = [presence fromStr];
    NSString *body = nil;

    // 别人请求加为好友
    if (!user) {
        if (![displayName isEqualToString:jidStrBare])
        {
            body = [NSString stringWithFormat:@"Buddy request from %@ <%@>", displayName, jidStrBare];
        }
        else
        {
            body = [NSString stringWithFormat:@"Buddy request from %@", displayName];
        }


        if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
        {
            [UIAlertView showWithTitle:displayName message:body cancelButtonTitle:@"拒绝" otherButtonTitles:@[@"同意"] tapBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
                
                if (buttonIndex == 0) {
                    [self.xmppRoster rejectPresenceSubscriptionRequestFrom:[presence from]];
                }else{
                    [self.xmppRoster acceptPresenceSubscriptionRequestFrom:[presence from] andAddToRoster:YES];
                }
            }];
        }
        else
        {
            // We are not active, so use a local notification instead
            UILocalNotification *localNotification = [[UILocalNotification alloc] init];
            localNotification.alertAction = @"Not implemented";
            localNotification.alertBody = body;

            [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
        }
    }else{
    }
}


//删除好友，name为好友账号
//- (void)removeBuddy:(NSString *)name
//{
//    XMPPJID *jid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@%@",name,kHost]];
//
//    [[self xmppRoster] removeUser:jid];
//}

//
- (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{

    // <query xmlns="jabber:iq:roster"></query>
    NSXMLElement *query = [iq elementForName:@"query" xmlns:@"jabber:iq:roster"];
    if (query) {
        NSArray *items = [query elementsForName:@"item"];

        // 如果通讯录为空，清空本地通讯录
        if (items.count == 0) {
            [self deleteAllRoster];
            // post notify
//            [self deleteAllRecentContact];
        }
    }

    return YES;
}

//
//
- (BOOL)deleteAllRoster
{
    NSManagedObjectContext *context = [self managedObjectContext_roster];

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"XMPPUserCoreDataStorageObject"
                                              inManagedObjectContext:context];
    [fetchRequest setEntity:entity];

    NSArray *objects = [context executeFetchRequest:fetchRequest error:NULL];
    if (objects.count > 0) {

        for (NSManagedObject *managedObject in objects) {
            [context deleteObject:managedObject];
        }

        NSError *error = nil;
        if (![context save:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            return NO;
        }
        return YES;
    }

    return NO;
}


- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
    NSLog(@"收到消息了: %@",message.description);

    if ([message isChatMessageWithBody])
    {
        XMPPUserCoreDataStorageObject *user = [_xmppRosterStorage userForJID:[message from]
                                                                  xmppStream:_xmppStream
                                                        managedObjectContext:[self managedObjectContext_roster]];

        NSString *body = [[message elementForName:@"body"] stringValue];
        NSString *displayName = [user displayName];

        if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
        {
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:displayName
                                                                message:body
                                                               delegate:nil
                                                      cancelButtonTitle:@"Ok"
                                                      otherButtonTitles:nil];
            [alertView show];
        }
        else
        {
            // We are not active, so use a local notification instead
            UILocalNotification *localNotification = [[UILocalNotification alloc] init];
            localNotification.alertAction = @"Ok";
            localNotification.alertBody = [NSString stringWithFormat:@"From: %@\n\n%@",displayName,body];

            [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
        }
    }

}


//认证失败的回调
-(void)xmppStream:sender didNotAuthenticate:(DDXMLElement *)error
{
    NSLog(@"认证失败 : %@",error.description);
}

- (void)xmppStream:(XMPPStream *)sender didReceiveError:(NSXMLElement *)error
{
    NSLog(@"didReceiveError: %@",error.description);
}
- (void)xmppStream:(XMPPStream *)sender didSendIQ:(XMPPIQ *)iq
{
    NSLog(@"didSendIQ:%@",iq.description);
}
- (void)xmppStream:(XMPPStream *)sender didSendMessage:(XMPPMessage *)message
{
    NSLog(@"didSendMessage:%@",message.description);
}
- (void)xmppStream:(XMPPStream *)sender didSendPresence:(XMPPPresence *)presence
{
    NSLog(@"didSendPresence:%@",presence.description);
}
- (void)xmppStream:(XMPPStream *)sender didFailToSendIQ:(XMPPIQ *)iq error:(NSError *)error
{
    NSLog(@"didFailToSendIQ:%@",error.description);
}
- (void)xmppStream:(XMPPStream *)sender didFailToSendMessage:(XMPPMessage *)message error:(NSError *)error
{
    NSLog(@"didFailToSendMessage:%@",error.description);
}
- (void)xmppStream:(XMPPStream *)sender didFailToSendPresence:(XMPPPresence *)presence error:(NSError *)error
{
    NSLog(@"didFailToSendPresence:%@",error.description);
}
- (void)xmppStreamWasToldToDisconnect:(XMPPStream *)sender
{
    NSLog(@"xmppStreamWasToldToDisconnect");
}
- (void)xmppStreamConnectDidTimeout:(XMPPStream *)sender
{
    NSLog(@"xmppStreamConnectDidTimeout");
}
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
    NSLog(@"xmppStreamDidDisconnect: %@",error.description);
}


@end
